package boot

import (
	"fmt"
	"github.com/wendy512/iec104/pkg/global"
	nativeLog "github.com/wendy512/iec104/pkg/logger"
	"log"
	"os"
	"time"

	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

func LoggerInit() {
	// 获取日志记录配置项
	cfg := global.Config.Logger
	// 创建logs目录
	creteLogsPath(cfg.LogPath)
	// 创建日志zap日志记录器
	logger := newLogger(cfg.LogPath, cfg.LogName, cfg.Level, cfg.SaveDays, cfg.PrintStd)
	// 注册系统异常处理函数，logger.Sync()后刷新日志文件
	RegisterExceptionHandleFunc(func() { logger.Sync() }, "Logger", 4)
	// 设置全局日志记录器实例
	nativeLog.SetLogger(logger)
}

// 创建logs目录
func creteLogsPath(logsPath string) {
	exist, err := isLogsPathExists(logsPath)
	if err != nil {
		log.Fatalf("get dir error![%v]\n", err)
	}

	if !exist {
		// 创建文件夹
		err := os.Mkdir(logsPath, os.ModePerm)
		if err != nil {
			log.Fatalf("mkdir failed![%v]\n", err)
		}
	}
}

// 判断文件夹是否存在
func isLogsPathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func newLogger(path, baseFile, level string, saveDays int, printStd bool) *zap.SugaredLogger {
	// 日志分割器（Hook）
	lumberJackLogger := &lumberjack.Logger{
		Filename: fmt.Sprintf("%s/%s.log", path, baseFile), // 日志文件的位置（路径+文件名）
		MaxSize:  256,                                      // 日志分割前，单个日志文件大小（单位：MB）
		//MaxBackups: saveDays,                             // 历史日志文件保存的最大个数
		MaxAge:   saveDays, // 历史日志文件保存的最大天数
		Compress: true,     // 历史日志文件是否压缩保存
	}

	// 日志编码器
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:       "time",                      // 时间戳字段Key名
		LevelKey:      "level",                     // 日志等级字段Key名
		CallerKey:     "file",                      // 日志记录文件+行数字段Key名
		MessageKey:    "msg",                       // 日志内容字段Key名
		StacktraceKey: "stacktrace",                // 堆栈跟踪字段Key名
		LineEnding:    zapcore.DefaultLineEnding,   // 换行符
		EncodeLevel:   zapcore.CapitalLevelEncoder, // 日志等级
		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendString(t.Format(`2006-01-02 15:04:05.000`)) // 事件戳格式
		},
		EncodeDuration: zapcore.MillisDurationEncoder, // 日志记录时间戳等级（毫秒级）
		// EncodeCaller:   zapcore.ShortCallerEncoder,    // 日志记录文件+行数（短记录）本系统使用自定义的Caller
	}

	// 设置日志级别
	atomicLevel := zap.NewAtomicLevel()
	switch level {
	case "debug":
		atomicLevel.SetLevel(zap.DebugLevel)
	case "release":
		atomicLevel.SetLevel(zap.InfoLevel)
	}

	// 以Json格式记录日志
	jsonEncoder := zapcore.NewJSONEncoder(encoderConfig)
	var writeSyncer zapcore.WriteSyncer
	if printStd {
		// 输出到终端
		writeSyncer = zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(lumberJackLogger))
	} else {
		// 输出到文件
		writeSyncer = zapcore.AddSync(lumberJackLogger)
	}
	// 设置日志记录就参数
	core := zapcore.NewCore(jsonEncoder, writeSyncer, atomicLevel.Level())
	// 构建日志记录器
	logger := zap.New(core)
	// zap.AddCaller(),   // 开启开发模式，堆栈跟踪 本系统使用自定义的Caller
	// zap.Development(), // 开启文件及行号

	return logger.Sugar()
}
